/**
  * @file 		buffer.c
  * @brief		环形缓存逻辑文件，主要实现环形缓存相关的功能函数。
  *
  * @copyright  Copyright (c) 2020~2030 ShenZhen Dxtc Technology Co., Ltd. 
  * All rights reserved.
  *
  * @version	v3.1
  * @author		FengLi
  * @date 		2021-08-02
  *
  * @note		鼎新同创·智能锁
  * 
  * @par 修改日志:
  * <1> 2021/08/02 v3.1 FengLi 创建初始版本
  *******************************************************************/
#include "osal.h"
#include "device.h"

/** @brief   计算环形缓存里面可以读的数据个数 */
#define OSAL_RbCanRead(rb)  ( (rb->read <= rb->write) ? ( (rb->write - rb->read) / rb->size ) : ( rb->len - ((rb->read - rb->write) / rb->size) ) )

/** @brief   计算环形缓存里面可以写的数据个数 */
#define OSAL_RbCanWrite(rb) ( rb->len - OSAL_RbCanRead(rb) )

/** @brief 环形缓存数据结构  */ 
typedef struct
{
	uint16_t len;   ///< 缓存长度（数据个数）
	uint16_t size;  ///< 每个数据的大小
	volatile uint8_t *write;  ///< 写函数指针
	volatile uint8_t *read;   ///< 读函数指针
	volatile uint8_t buff[];  ///< 数据缓存区
}RingBuffer_stu_t;


/**
  * @brief  创建环形缓存
  * @details 详细说明：无
  *    
  * @param[in]  buffLength：缓存长度
  * @param[in]  itemSize：条目大小
  *         
  * @return 返回缓存句柄，错误返回NULL
  */
RingBufferHandle_t OSAL_RingBufferCreate(uint16_t buffLength, uint16_t itemSize)
{
	RingBuffer_stu_t *pRB;
	
	if (buffLength == 0 || itemSize == 0)
	{
		return NULL;
	}
	buffLength = buffLength + 1;
	pRB = (RingBuffer_stu_t*)OSAL_Malloc(sizeof(RingBuffer_stu_t) + buffLength * itemSize);
	if (pRB != NULL)
	{
		pRB->len = buffLength;
		pRB->size = itemSize;
		pRB->read = pRB->buff;
		pRB->write = pRB->buff;
	}
	return (RingBufferHandle_t)pRB;
}

/**
  * @brief  往环形缓存写入一个数据
  * @details 详细说明:该函数允许中断调用（一般是中断收到数据，就调用该函数将数据写入缓存）
  *         
  * @param[in]  handle：缓存句柄
  * @param[in]  pData：数据首地址
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_RingBufferWrite(RingBufferHandle_t handle, void *pData)
{
	RingBuffer_stu_t *pRB = (RingBuffer_stu_t *)handle;
	
	if (pRB == NULL || pData == NULL)
	{
		return ERROR;
	}
	
	if (OSAL_RbCanWrite(pRB) <= 1)
	{
		return ERROR;
	}
	
	memcpy((void*)(pRB->write), pData, pRB->size);
	
	pRB->write += pRB->size;
	if (pRB->write == (pRB->buff + pRB->len * pRB->size))
	{
		pRB->write = pRB->buff;
	}
	return SUCCESS;
}

/**
  * @brief  从环形缓存里面读出读取有效数据的长度
  * @details 详细说明：无
  *    
  * @param[in]  handle：缓存句柄
  *         
  * @return 返回数据长度（RB_BUF里面的有效字节数）
  */
uint32_t OSAL_RingBufferGetValidSize(RingBufferHandle_t handle)
{
	RingBuffer_stu_t *pRB = (RingBuffer_stu_t *)handle;
	
	if (pRB == NULL)
	{
		return 0;
	}
	return OSAL_RbCanRead(pRB);
}

/**
  * @brief  从环形缓存里面读出一个数据
  * @details 详细说明：无
  *    
  * @param[in]  handle：缓存句柄
  * @param[in]  pData：数据首地址
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_RingBufferRead(RingBufferHandle_t handle, void *pData)
{
	RingBuffer_stu_t *pRB = (RingBuffer_stu_t *)handle;
	
	if (pRB == NULL || pData == NULL)
	{
		return ERROR;
	}
	
	if (OSAL_RbCanRead(pRB) == 0)
	{
		return ERROR;
	}
	
	memcpy(pData, (void*)(pRB->read), pRB->size);
	
	pRB->read += pRB->size;
	if (pRB->read == (pRB->buff + pRB->len * pRB->size))
	{
		pRB->read = pRB->buff;
	}
	return SUCCESS;
}

/**
  * @brief  从环形缓存里面读出一个数据
  * @details 详细说明：读出后不清除buf中的读出数据
  * 
  * @param[in]  handle：缓存句柄
  * @param[in]  pData：数据首地址
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_RingBufferRead_No_Clear(RingBufferHandle_t handle, void *pData)
{
	RingBuffer_stu_t *pRB = (RingBuffer_stu_t *)handle;
	
	if (pRB == NULL || pData == NULL)
	{
		return ERROR;
	}
	
	if (OSAL_RbCanRead(pRB) == 0)
	{
		return ERROR;
	}
	
	memcpy(pData, (void*)(pRB->read), pRB->size);
	
	return SUCCESS;
}

/**
  * @brief   复位环形缓存
  * @details 详细说明：清空缓存里面的所有数据
  *
  * @param[in]  handle：缓存句柄
  *         
  * @return 【SUCCEE】：成功   【ERROR】：失败（错误)
  */
ErrorStatus OSAL_RingBufferReset(RingBufferHandle_t handle)
{
	RingBuffer_stu_t *pRB = (RingBuffer_stu_t *)handle;
	
	if (pRB != NULL)
	{
		Device_EnterCritical();
		pRB->read = pRB->buff;
		pRB->write = pRB->buff;
		Device_ExitCritical();
		return SUCCESS;
	}
	return ERROR;
}
